package com.AdvancedDemos.多态;

public class 多态_instanceof {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();//用父类变量接子类B实例
        A a3 = new C();//用父类变量接子类C实例

        a1.run();
        a2.run();
        a3.run();

//A is running
//B is running
//C is running
//A
//A
//A

        //多态具体表现为"对象多态,行为多态",对象多态就是指父类变量可以指向任意子类实例,行为多态就是指用父类变量调不同子类中重写父类同一方法的成员方法,实际执行的行为不用


        //但是成员变量不存在多态,父类变量只会调用父类自己的成员变量
        System.out.println(a1.str);
        System.out.println(a2.str);
        System.out.println(a2.str);


        System.out.println("-=-=-=-=-=-=-=-");
        用父类变量做形参子类对象做实参(a1);
        用父类变量做形参子类对象做实参(a2);
        用父类变量做形参子类对象做实参(a3);
        System.out.println("-=-=-=-=-=-=-=-");

        /**
         * 注意父类不可以直接调用子类中特有的方法,因为不可见,需要强转成子类类型
         */
        a1.a();
        ((B) a2).b();

        C cTemp = (C) a3;
        cTemp.c();

//        B bTemp = (B) a3;
//        bTemp.b();//如果不管父类变量指向的实际子类类型而强行将其转成其他子类类型,如此处a3指向的对象实际是C类型的,但强转成了B类型,尽管编译不会报错ClassCastException,但运行会报错
        System.out.println("---------------");
        //为了避免出现类型转换错误,可以使用instanceof关键字来判断对象的实际类型
        //a instanceof A 如果a是A类型(或A的子类)的实例,那么返回true,否则返回false

        if (a3 instanceof B) {
            System.out.println("a3 is instance of B");
            B btemp = (B) a3;
            System.out.print("调用B中的b函数:");
            btemp.b();
        }
        if (a3 instanceof C) {
            System.out.println("a3 is instance of C");
            C ctemp = (C) a3;
            System.out.print("调用C中的c函数:");
            ctemp.c();
        }


    }


    public static void 用父类变量做形参子类对象做实参(A temp) {//通过多态,可以用父类变量做形参,就可以用任意子类对象作为实参,实现同一个函数给不同参数时各自做不同的事
        temp.run();
    }

}

class A {
    String str = "A";

    void run() {
        System.out.println("A is running");
    }

    void a() {
        System.out.println("a");
    }
}

class B extends A {
    String str = "B";

    @Override
    void run() {
        System.out.println("B is running");
    }

    void b() {
        System.out.println("b");
    }
}

class C extends A {
    String str = "C";

    @Override
    void run() {
        System.out.println("C is running");
    }

    void c() {
        System.out.println("c");
    }
}
